package com.lib.framework.other.observable

import java.util.*

/**
 * Copyright (C), 2020-2020, 享物说
 * FileName: Observable02
 * Author: keanbin
 * Date: 2020-02-13 22:21
 * Description: 被观察者
 * History:
 * <author> <time> <version> <desc>
 * 作者姓名 修改时间 版本号 描述
 */
open class Observable02<T> {
    private val obs = Vector<Observer02<T>>()

    /**
     * Adds an observer to the set of observers for this object, provided
     * that it is not the same as some observer already in the set.
     * The order in which notifications will be delivered to multiple
     * observers is not specified. See the class comment.
     *
     * @param   o   an observer to be added.
     * @throws NullPointerException   if the parameter o is null.
     */
    @Synchronized
    fun addObserver(o: Observer02<T>) {
        if (!obs.contains(o)) {
            obs.addElement(o)
        }
    }

    /**
     * Deletes an observer from the set of observers of this object.
     * Passing <CODE>null</CODE> to this method will have no effect.
     * @param   o   the observer to be deleted.
     */
    @Synchronized
    fun deleteObserver(o: Observer02<T>) {
        obs.removeElement(o)
    }

    /**
     * If this object has changed, as indicated by the
     * `hasChanged` method, then notify all of its observers
     * and then call the `clearChanged` method to indicate
     * that this object has no longer changed.
     *
     *
     * Each observer has its `update` method called with two
     * arguments: this observable object and the `arg` argument.
     *
     * @param   arg   any object.
     * @see java.util.Observable.clearChanged
     * @see java.util.Observable.hasChanged
     * @see java.util.Observer.update
     */
    @Synchronized
    fun notifyObservers(data: T?) {
        val arrLocal: Array<Any>

        synchronized(this) {
            arrLocal = obs.toTypedArray()
        }

        for (i in arrLocal.indices.reversed())
            (arrLocal[i] as Observer02<T>).update(data)
    }

    /**
     * Clears the observer list so that this object no longer has any observers.
     */
    @Synchronized
    fun deleteObservers() {
        obs.removeAllElements()
    }

    /**
     * Returns the number of observers of this <tt>Observable02</tt> object.
     *
     * @return  the number of observers of this object.
     */
    @Synchronized
    fun countObservers(): Int {
        return obs.size
    }
}